﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using HPPServer;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;
using System.Collections;
using HPPNet;

namespace HPP.UnitTest
{
    
    
    /// <summary>
    ///这是 SSServerTest 的测试类，旨在
    ///包含所有 SSServerTest 单元测试
    ///</summary>
    [TestClass()]
    public class SSServerTest
    {


        private TestContext testContextInstance;

        private readonly string TestShareXMLString = "<?xml version = \"1.0\" encoding=\"utf-8\" ?><Info><Client Port=\"9998\" /><ShareFiles><File FileName=\"c#\" Hash=\"hash_c#\" Size=\"888\"></File><File FileName=\"C++\" Hash=\"hash_C++\" Size=\"1048576\"></File></ShareFiles></Info>";

        /// <summary>
        ///获取或设置测试上下文，上下文提供
        ///有关当前测试运行及其功能的信息。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 附加测试属性

        private PrivateObject param0;
        private SSServer_Accessor target;

        // 
        //编写测试时，还可使用以下属性:
        //
        //使用 ClassInitialize 在运行类中的第一个测试前先运行代码
        [ClassInitialize()]
        public static void MyClassInitialize(TestContext testContext)
        {
           
        }
        //
        //使用 ClassCleanup 在运行完类中的所有测试后再运行代码
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //使用 TestInitialize 在运行每个测试前先运行代码
        [TestInitialize()]
        public void MyTestInitialize()
        {
            param0 = new PrivateObject(new SSServer(0x3, 0xFFFF)); // TODO: 初始化为适当的值
            target = new SSServer_Accessor(param0); // TODO: 初始化为适当的值
        }
        
        //使用 TestCleanup 在运行完每个测试后运行代码
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        #region ProceesHttpReq

        /// <summary>
        /// ProcessHttpReq 的测试
        /// 
        /// 输入: endpoint 为 null
        /// 
        /// 预期输出：null
        ///</summary>
        /// <remarks>
        /// 2009-08-19
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ProcessHttpReq_when_endpoint_is_null()
        {
            Assert.AreEqual(null, target.ProcessHttpReq(null, new Hashtable(), "something"));
        }

        /// <summary>
        /// ProcessHttpReq 的测试
        /// 
        /// 输入: headers 为 null
        /// 
        /// 预期输出：null
        ///</summary>
        /// <remarks>
        /// 2009-08-19
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ProcessHttpReq_when_headers_is_null()
        {
            Assert.AreEqual(null, target.ProcessHttpReq(new IPEndPoint(IPAddress.Loopback, 0xFF), null, "something"));
        }

        /// <summary>
        /// ProcessHttpReq 的测试
        /// 
        /// 输入: headers 为 空
        /// 
        /// 预期输出：null
        ///</summary>
        /// <remarks>
        /// 2009-08-19
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ProcessHttpReq_when_headers_is_empty()
        {
            Assert.AreEqual(null, target.ProcessHttpReq(new IPEndPoint(IPAddress.Loopback, 0xFF), new Hashtable(), "something"));
        }

        /// <summary>
        /// ProcessHttpReq 的测试
        /// 
        /// 输入: body 为 null
        /// 
        /// 预期输出：null
        ///</summary>
        /// <remarks>
        /// 2009-08-19
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ProcessHttpReq_when_body_is_null()
        {
            Assert.IsInstanceOfType(target.ProcessHttpReq(new IPEndPoint(IPAddress.Loopback, 0xFF), new Hashtable(){ {"Method","POST"} }, null), typeof(VoidResponse));

            AssertNoRecord();
        }

        /// <summary>
        /// ProcessHttpReq 的测试
        /// 
        /// 输入: 获取用户列表请求
        /// 
        /// 预期输出：typeof(StringResponse)
        ///</summary>
        /// <remarks>
        /// 2009-08-19
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ProcessHttpReq_when_get_userlist_of_a_file()
        {
            Assert.IsInstanceOfType(target.ProcessHttpReq(new IPEndPoint(IPAddress.Loopback, 0xFF),
                new Hashtable()
                    {
                        { "Method", "GET" },
                        { "Url", "/abc.txt|hash/"}
                    },
                null), typeof(StringResponse));
        }

        /// <summary>
        /// ProcessHttpReq 的测试
        /// 
        /// 输入: 搜索文件请求
        /// 
        /// 预期输出：typeof(StringResponse)
        ///</summary>
        /// <remarks>
        /// 2009-08-19
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ProcessHttpReq_when_search_file()
        {
            Assert.IsInstanceOfType(target.ProcessHttpReq(new IPEndPoint(IPAddress.Loopback, 0xFF),
                new Hashtable()
                    {
                        { "Method", "GET" },
                        { "Url", "/abc.txt|none/"}
                    },
                null), typeof(StringResponse));
        }

        #endregion ProcessHttpReq

        #region ParseUrl

        /// <summary>
        /// 测试ParseUrl()
        /// 
        /// 输入：url为null
        /// 
        /// 预期输出：out Hashtable urlInfo为空
        /// 
        /// </summary>
        /// <remarks>
        /// 2009-08-17
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ParseUrl_url_is_null()
        {
            
            
            Hashtable actual;
            Hashtable expected = null;

            target.ParseUrl(out actual, null);

            Assert.AreEqual(expected, actual);
        }


        /// <summary>
        /// 测试ParseUrl()
        /// 
        /// 输入：url为 empty
        /// 
        /// 预期输出：out Hashtable urlInfo为空
        /// 
        /// </summary>
        /// <remarks>
        /// 2009-08-17
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ParseUrl_url_is_empty()
        {
            Hashtable expected = null;
            Hashtable actual;
            target.ParseUrl(out actual, string.Empty);

            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        /// 测试ParseUrl()
        /// 
        /// 输入：url不带前导斜杠
        /// 
        /// 预期输出：对应正确的urlInfo
        /// 
        /// </summary>
        /// <remarks>
        /// 2009-08-17
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ParseUrl_url_has_no_prefix_slash()
        {
            Hashtable actual = null;
            Hashtable expected = new Hashtable()
                                     {
                                         {"FileName", "abc.txt"},
                                         {"Hash","hash1234ABCD"}
                                     };

            target.ParseUrl(out actual, "abc.txt|hash1234ABCD/");
            Assert.AreEqual(expected["FileName"], actual["FileName"]);
            Assert.AreEqual(expected["Hash"], actual["Hash"]);
        }

        /// <summary>
        /// 测试ParseUrl()
        /// 
        /// 输入：url不带后缀斜杠
        /// 
        /// 预期输出：对应正确的urlInfo
        /// 
        /// </summary>
        /// <remarks>
        /// 2009-08-17
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ParseUrl_url_has_no_suffix_slash()
        {
            Hashtable actual = null;
            Hashtable expected = new Hashtable()
                                     {
                                         {"FileName", "abc.txt"},
                                         {"Hash","hash1234ABCD"}
                                     };

            target.ParseUrl(out actual, "/abc.txt|hash1234ABCD");
            Assert.AreEqual(expected["FileName"], actual["FileName"]);
            Assert.AreEqual(expected["Hash"], actual["Hash"]);
        }

        /// <summary>
        /// 测试ParseUrl()
        /// 
        /// 输入：url不带前导和后缀斜杠
        /// 
        /// 预期输出：对应正确的urlInfo
        /// 
        /// </summary>
        /// <remarks>
        /// 2009-08-17
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ParseUrl_url_has_no_prefix_and_suffix_slash()
        {

            Hashtable actual = null;
            Hashtable expected = new Hashtable()
                                     {
                                         {"FileName", "abc.txt"},
                                         {"Hash","hash1234ABCD"}
                                     };

            target.ParseUrl(out actual, "abc.txt|hash1234ABCD");
            Assert.AreEqual(expected["FileName"], actual["FileName"]);
            Assert.AreEqual(expected["Hash"], actual["Hash"]);
        }

        /// <summary>
        /// 测试ParseUrl()
        /// 
        /// 输入：url带前导和后缀斜杠
        /// 
        /// 预期输出：对应正确的urlInfo
        /// 
        /// </summary>
        /// <remarks>
        /// 2009-08-17
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ParseUrl_url_has_prefix_and_suffix_slash()
        {

            Hashtable actual = null;
            Hashtable expected = new Hashtable()
                                     {
                                         {"FileName", "abc.txt"},
                                         {"Hash","hash1234ABCD"}
                                     };

            target.ParseUrl(out actual, "/abc.txt|hash1234ABCD/");
            Assert.AreEqual(expected["FileName"], actual["FileName"]);
            Assert.AreEqual(expected["Hash"], actual["Hash"]);
        }

        /// <summary>
        /// 测试ParseUrl()
        /// 
        /// 输入：url不带管道符竖线
        /// 
        /// 预期输出：out Hashtable urlInfo为空
        /// 
        /// </summary>
        /// <remarks>
        /// 2009-08-17
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_ParseUrl_url_has_no_pipe()
        {
            Hashtable actual = null;
            Hashtable expected = null;

            target.ParseUrl(out actual, "abc.txthash1234ABCD");
            Assert.AreEqual(expected, actual);
        }

        #endregion 

        #region SaveUserFilesInfo

        /// <summary>
        /// SaveUsersFileInfo 的测试
        /// 
        /// 输入: data为null
        /// 
        /// 预期输出：没有项被添加
        ///</summary>
        /// <remarks>
        /// 2009-08-18
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_SaveUsersFileInfo_when_data_is_null()
        {
            target.SaveUserFilesInfo(null, new IPEndPoint(IPAddress.Loopback, 0xFF));

            AssertNoRecord();
        }

        /// <summary>
        /// SSServer没有记录的断言
        /// </summary>
        private void AssertNoRecord()
        {
            Assert.AreEqual(0, target.hashUser.Count);
            Assert.AreEqual(0, target.fileNameHash.Count);
        }

        /// <summary>
        /// SaveUsersFileInfo 的测试
        /// 
        /// 输入: data为empty
        /// 
        /// 预期输出：没有项被添加
        ///</summary>
        /// <remarks>
        /// 2009-08-18
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_SaveUsersFileInfo_when_data_is_empty()
        {

            target.SaveUserFilesInfo(string.Empty, new IPEndPoint(IPAddress.Loopback, 0xFF));

            AssertNoRecord();
        }

        /// <summary>
        /// SaveUsersFileInfo 的测试
        /// 
        /// 输入: data为非法格式
        /// 
        /// 预期输出：没有项被添加
        ///</summary>
        /// <remarks>
        /// 2009-08-18
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_SaveUsersFileInfo_when_data_format_is_illegal()
        {

            target.SaveUserFilesInfo("abc/skfir", new IPEndPoint(IPAddress.Loopback, 0xFF));

            AssertNoRecord();
        }

        /// <summary>
        /// SaveUsersFileInfo 的测试
        /// 
        /// 输入: data为合法的、无共享文件格式
        /// 
        /// 预期输出：没有项被添加
        ///</summary>
        /// <remarks>
        /// 2009-08-18
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_SaveUsersFileInfo_when_data_is_legal_for_no_share_file()
        {
            string xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><ShareFiles></ShareFiles>";


            target.SaveUserFilesInfo(xml, new IPEndPoint(IPAddress.Loopback, 0xFF));

            AssertNoRecord();
        }

        /// <summary>
        /// SaveUsersFileInfo 的测试
        /// 
        /// 输入: data为合法的、无共享文件格式
        /// 
        /// 预期输出：没有项被添加
        ///</summary>
        /// <remarks>
        /// 2009-08-18
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_SaveUsersFileInfo_when_endpoint_is_null()
        {
            string xml = this.TestShareXMLString;

            target.SaveUserFilesInfo(xml, null);

            AssertNoRecord();
        }

        /// <summary>
        /// SaveUsersFileInfo 的测试
        /// 
        /// 输入: data为合法的、有共享文件格式
        /// 
        /// 预期输出：项被正确添加
        ///</summary>
        /// <remarks>
        /// 2009-08-18
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_SaveUsersFileInfo_when_data_is_legal_for_share_file()
        {
            string xml = this.TestShareXMLString;

            IPEndPoint testEndPoint = new IPEndPoint(IPAddress.Loopback, 0xFF);
            target.SaveUserFilesInfo(xml, testEndPoint);

            Assert.AreEqual(2, target.hashUser.Count);

            Assert.AreEqual(2, target.fileNameHash.Count);

            FileInformations actualFirstFileInfo = target.hashUser["hash_c#"];

            Assert.AreEqual(888 / target.BLOCKSIZE + 1, actualFirstFileInfo.BlockNumber);
            Assert.AreEqual(1, target.hashUser["hash_C++"].BlockNumber);

            Assert.AreEqual(1, actualFirstFileInfo.IPEndPointList.Count);

            Assert.AreEqual(testEndPoint , actualFirstFileInfo.IPEndPointList.First());

            Assert.AreEqual(888 % 1048576, actualFirstFileInfo.LastBlockSize);
            Assert.AreEqual(target.BLOCKSIZE, target.hashUser["hash_C++"].LastBlockSize);

            Assert.AreEqual(888, actualFirstFileInfo.Size);

            Assert.AreEqual("hash_c#" ,target.fileNameHash["c#"]);


            target.SaveUserFilesInfo(xml, new IPEndPoint(IPAddress.Parse("202.96.140.58"),0xFF));

            Assert.AreEqual(2, target.hashUser["hash_c#"].IPEndPointList.Count);
        }

        #endregion SaveUserFilesInfo

        #region SearchFile

        /// <summary>
        /// SearchFile 的测试
        /// 
        /// 输入: filename is null
        /// 
        /// 预期输出：没找到相应的资源
        ///</summary>
        /// <remarks>
        /// 2009-08-18
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_SearchFile_when_filename_is_null()
        {
            string xml = this.TestShareXMLString;

            IPEndPoint testEndPoint = new IPEndPoint(IPAddress.Loopback, 0xFF);
            target.SaveUserFilesInfo(xml, testEndPoint);

            string actual = target.SearchFile(null);

            XDocument doc = XmlAssert.AssertValid(actual);

            Assert.AreEqual(false, doc.Descendants("Files").Single().HasElements);
            
        }

        /// <summary>
        /// SearchFile 的测试
        /// 
        /// 输入: filename is empty
        /// 
        /// 预期输出：没找到相应的资源
        ///</summary>
        /// <remarks>
        /// 2009-08-18
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_SearchFile_when_filename_is_empty()
        {
            string xml = this.TestShareXMLString;

            IPEndPoint testEndPoint = new IPEndPoint(IPAddress.Loopback, 0xFF);
            target.SaveUserFilesInfo(xml, testEndPoint);

            string actual = target.SearchFile(string.Empty);

            XDocument doc = XmlAssert.AssertValid(actual);

            Assert.AreEqual(false, doc.Descendants("Files").Single().HasElements);

        }

        /// <summary>
        /// SearchFile 的测试
        /// 
        /// 输入: 已经存在的Filename的一部分
        /// 
        /// 预期输出：模糊搜索对应的结果列表
        ///</summary>
        /// <remarks>
        /// 2009-08-18
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_SearchFile_when_filename_is_a_part_of_the_existed_record()
        {
            string xml = this.TestShareXMLString;

            IPEndPoint testEndPoint = new IPEndPoint(IPAddress.Loopback, 0xFF);
            target.SaveUserFilesInfo(xml, testEndPoint);

            string actual = target.SearchFile("c");

            XDocument doc = XmlAssert.AssertValid(actual);

            Assert.AreEqual(2, doc.Descendants("File").Count());

            
            //Regex regex = new Regex("<\\?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"\\?><Files>(?:(?:\\r\\n)|.)*</Files>");


            //Assert.AreEqual(true, regex.IsMatch(actual));

            //Regex regexFileResult = new Regex("<File FileName=\"c#\" Hash=\"hash_c#\"\\s*/>");


            //Assert.AreEqual(true, regexFileResult.IsMatch(actual));
            

        }

        #endregion

        #region GetFileInformation

        /// <summary>
        /// GetFileInformation 的测试
        /// 
        /// 输入: filehash is null
        /// 
        /// 预期输出：没找到相应的资源
        ///</summary>
        /// <remarks>
        /// 2009-08-19
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_GetFileInformation_when_filehash_is_null()
        {
            string xml = this.TestShareXMLString;

            IPEndPoint testEndPoint = new IPEndPoint(IPAddress.Loopback, 0xFF);
            target.SaveUserFilesInfo(xml, testEndPoint);


            string actual = target.GetFileInfomation(null);

            XDocument doc = XmlAssert.AssertValid(actual);

            Assert.AreEqual(false, doc.Descendants("UserList").Single().HasElements);

        }


        /// <summary>
        /// GetFileInformation 的测试
        /// 
        /// 输入: filehash is empty
        /// 
        /// 预期输出：没找到相应的资源
        ///</summary>
        /// <remarks>
        /// 2009-08-19
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_GetFileInformation_when_filehash_is_empty()
        {
            string xml = this.TestShareXMLString;

            IPEndPoint testEndPoint = new IPEndPoint(IPAddress.Loopback, 0xFF);
            target.SaveUserFilesInfo(xml, testEndPoint);


            string actual = target.GetFileInfomation(string.Empty);

            XDocument doc = XmlAssert.AssertValid(actual);

            Assert.AreEqual(false, doc.Descendants("UserList").Single().HasElements);

        }


        /// <summary>
        /// GetFileInformation 的测试
        /// 
        /// 输入: filehash不在列表里
        /// 
        /// 预期输出：没找到相应的资源
        ///</summary>
        /// <remarks>
        /// 2009-08-19
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_GetFileInformation_when_filehash_does_not_exist()
        {
            string xml = this.TestShareXMLString;

            IPEndPoint testEndPoint = new IPEndPoint(IPAddress.Loopback, 0xFF);
            target.SaveUserFilesInfo(xml, testEndPoint);


            string actual = target.GetFileInfomation(string.Empty);

            XDocument doc = XmlAssert.AssertValid(actual);

            Assert.AreEqual(false, doc.Descendants("UserList").Single().HasElements);

        }

        /// <summary>
        /// GetFileInformation 的测试
        /// 
        /// 输入: filehash在列表里
        /// 
        /// 预期输出：找到相应的资源
        ///</summary>
        /// <remarks>
        /// 2009-08-19
        /// vls
        /// </remarks>
        [TestMethod()]
        [DeploymentItem("HPPServer.exe")]
        public void Test_GetFileInformation_when_filehash_exists()
        {
            string xml = this.TestShareXMLString;

            IPEndPoint testEndPoint = new IPEndPoint(IPAddress.Loopback, 0xFF);
            target.SaveUserFilesInfo(xml, testEndPoint);


            string actual = target.GetFileInfomation("hash_c#");

            XDocument doc = XmlAssert.AssertValid(actual);

            Assert.AreEqual(1, doc.Descendants("User").Count());

            Assert.AreEqual(IPAddress.Loopback.ToString(), doc.Descendants("User").Single().Attribute("IP").Value);

            Assert.AreEqual("9998", doc.Descendants("User").Single().Attribute("Port").Value);// change to response client's csserver port instead of send socket port

            Assert.AreEqual("888", doc.Descendants("FileSize").Single().Attribute("Size").Value);

            Assert.AreEqual("1", doc.Descendants("Blocks").Single().Attribute("Number").Value);

            Assert.AreEqual("888", doc.Descendants("LastBlock").Single().Attribute("Size").Value);

        }

        #endregion GetFileInformation
    }
}
